/*
 * Copyright 1999-2018 Alibaba Group Holding Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.alibaba.nacos.bootstrap;

import com.alibaba.nacos.NacosServerBasicApplication;
import com.alibaba.nacos.NacosServerWebApplication;
import com.alibaba.nacos.console.NacosConsole;
import com.alibaba.nacos.core.listener.startup.NacosStartUp;
import com.alibaba.nacos.core.listener.startup.NacosStartUpManager;
import com.alibaba.nacos.sys.env.Constants;
import com.alibaba.nacos.sys.env.DeploymentType;
import com.alibaba.nacos.sys.env.EnvUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * @author nacos
 * <p>
 * nacos console 源码运行，方便开发 生产从官网下载zip最新版集群配置运行
 */
@Slf4j
public class PigNacosApplication {

	/**
	 * 独立模式系统属性名称
	 */
	private static String STANDALONE_MODE = "nacos.standalone";

	public static void main(String[] args) {
		System.setProperty(STANDALONE_MODE, "true");

		/**
		 * 这段代码用于设置Nacos的部署类型：
		 *
		 * 1. 从系统属性中获取 [Constants.NACOS_DEPLOYMENT_TYPE](file://com\alibaba\nacos\sys\env\Constants.java#L27-L27) 的值，若未设置则使用默认值 [Constants.NACOS_DEPLOYMENT_TYPE_MERGED](file://com\alibaba\nacos\sys\env\Constants.java#L28-L28)；
		 * 2. 将获取到的字符串类型的部署类型转换为枚举类型 [DeploymentType](file://com\alibaba\nacos\sys\env\DeploymentType.java#L2-L14)；
		 * 3. 通过 [EnvUtil.setDeploymentType()](file://com\alibaba\nacos\sys\env\EnvUtil.java#L95-L95) 将当前环境的部署类型设置进去，供后续逻辑使用。
		 */
		String type = System.getProperty(Constants.NACOS_DEPLOYMENT_TYPE, Constants.NACOS_DEPLOYMENT_TYPE_MERGED);
		DeploymentType deploymentType = DeploymentType.getType(type);
		EnvUtil.setDeploymentType(deploymentType);

		/**
		 * 这段代码的功能是：
		 *
		 * 1. [NacosStartUpManager.start(NacosStartUp.CORE_START_UP_PHASE);](file://com\alibaba\nacos\core\listener\startup\NacosStartUpManager.java#L12-L12)
		 *    启动 Nacos 的核心启动阶段，初始化相关组件。
		 *
		 * 2. 创建并运行一个非 Web 类型的 Spring 应用上下文，用于加载 [NacosServerBasicApplication](file://com\alibaba\nacos\NacosServerBasicApplication.java#L6-L12) 类。
		 *    ```java
		 *    ConfigurableApplicationContext coreContext = new SpringApplicationBuilder(NacosServerBasicApplication.class)
		 *        .web(WebApplicationType.NONE)
		 *        .run(args);
		 *    ```
		 */
		NacosStartUpManager.start(NacosStartUp.CORE_START_UP_PHASE);
		ConfigurableApplicationContext coreContext = new SpringApplicationBuilder(NacosServerBasicApplication.class)
				.web(WebApplicationType.NONE)
				.run(args);

		/**
		 * 这段代码的功能是：
		 *
		 * 1. [NacosStartUpManager.start(NacosStartUp.WEB_START_UP_PHASE);](file://com\alibaba\nacos\core\listener\startup\NacosStartUpManager.java#L12-L12)
		 *    启动 Nacos 的 Web 启动阶段，初始化相关组件。
		 *
		 * 2. 创建并运行一个 Spring Web 应用上下文，用于启动 Nacos 的 Web 模块：
		 *    - 以 `NacosServerWebApplication.class` 为入口类
		 *    - 设置父上下文为 `coreContext`
		 *    - 使用传入的 `args` 参数启动应用
		 */
		NacosStartUpManager.start(NacosStartUp.WEB_START_UP_PHASE);
		ConfigurableApplicationContext serverWebContext = new SpringApplicationBuilder(NacosServerWebApplication.class)
				.parent(coreContext)
				.run(args);

		/**
		 * 这段 Java 代码的功能是：
		 *
		 * 1. [NacosStartUpManager.start(NacosStartUp.CONSOLE_START_UP_PHASE);](file://com\alibaba\nacos\core\listener\startup\NacosStartUpManager.java#L12-L12)
		 *    启动 Nacos 控制台模块的初始化流程。
		 *
		 * 2. 创建并运行一个 Spring 应用上下文，用于启动 Nacos 控制台应用：
		 *    - 使用 `SpringApplicationBuilder` 构建器创建上下文；
		 *    - 指定主类为 `NacosConsole.class`；
		 *    - 设置父上下文为 `coreContext`（通常是核心模块的上下文）；
		 *    - 通过 `.run(args)` 启动应用。
		 */
		NacosStartUpManager.start(NacosStartUp.CONSOLE_START_UP_PHASE);
		ConfigurableApplicationContext consoleContext = new SpringApplicationBuilder(NacosConsole.class)
				.parent(coreContext)
				.run(args);
	}

}
